-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client-auditor protocol #155
Conversation
cb64fbc
to
da139a7
Compare
8d48156
to
6577d92
Compare
My most concern here is how will this fit well with other auditor types (like Cosi and Blockchain). But I'm fine with this PR and happy to reorganize our code as things come later. |
Right, all of these auditor types are very distinct, but I think CoSi auditors and blockchain auditors are more extensions to the auditing protocol instead of complete replacements.
I'm not sure what you have in mind. Is your issue that the auditor protocol is part of the core protocol? Because as I said above, I think it should be. If/when we have more auditing options, like you said, we can re-think whether this makes sense. |
protocol/auditlog.go
Outdated
func newDirectoryHistory(signKey sign.PublicKey, str *m.SignedTreeRoot) *directoryHistory { | ||
h := new(directoryHistory) | ||
h.signKey = signKey | ||
h.snapshots = make(map[uint64]*m.SignedTreeRoot) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should str
be included in snapshots
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a big advantage to including the initially observed str
in snapshots
right away?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, no. I just thought it should be here at the first glance. But it doesn't matter :p
protocol/auditlog.go
Outdated
|
||
// IsKnownDirectory checks to see if an entry for the directory | ||
// address addr exists in the audit log l. IsKnownDirectory() does not | ||
// validate the entries themselves. It returns true if an entry exists, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpicking: double space here ;)
}, | ||
}, ReqSuccess | ||
} | ||
|
||
func (msg *Response) validate() error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we update these assertions for ObservedSTR(s)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think this makes sense, especially if we're going to have some generic HandleSTRs
function.
protocol/auditlog.go
Outdated
} | ||
|
||
if h := l.histories[req.DirectoryAddr]; h != nil { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to swap these 2 code blocks for consistency with directory.go
: return error immediately if h==nil
. The same for GetObservedSTR
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please point to code in directory.go
where this happens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we go: https://github.com/coniks-sys/coniks-go/blob/master/protocol/directory.go#L201-L215. I meant we return NewErrorResponse
earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@masomel: Please fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PTAL at 42da6b3
protocol/auditlog.go
Outdated
return false | ||
} | ||
|
||
// FIXME: pass Request message as param |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean Response? What do you think if we have a generic function like HandleResponse
in consistencychecks.go
and call Insert
, Update
, InsertRange
for each case? I would like to call it HandleDirectorySTRs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, you're right, this should be Response
. I also like the idea of having a generic HandleDirectorySTRs
function since there is a lot of potentially shared STR verification code between the auditor and the client. But Insert
, Update
and InsertRange
are specific to the auditor log, though, so I think it makes sense to keep those separate from consistencychecks.go
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But Insert, Update and InsertRange are specific to the auditor log, though, so I think it makes sense to keep those separate from consistencychecks.go.
Yes, of course.
Yes, I agree that too. |
protocol/consistencychecks.go
Outdated
@@ -100,6 +100,50 @@ func (cc *ConsistencyChecks) HandleResponse(requestType int, msg *Response, | |||
return CheckPassed | |||
} | |||
|
|||
// handleDirectorySTRs is supposed to be used by CONIKS clients to | |||
// handle auditor responses, and by CONIKS auditors to handle directory responses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure if this is supposed to be here since the file header states Implements all consistency check operations done by a CONIKS client on data received from a CONIKS directory.
. Maybe we should move verifySTR
and verifySTRConsistency
to str.go
? If you agree, we can add a TODO here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized this as well. I've started working on creating a more generic auditor
module that contains all the functionality clients and auditors need to verify/audit the STR consistency. What do you think? But I also think this belongs in a different PR since it requires for a verifySTRConsistencyInEpoch
to be implemented. I'll add a TODO.
I know you were already working on this when implementing the monitoring protocol. Do you think it would make sense to implement all the STR-related verification separate from the monitoring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree! I'll separate these code and open PR for each of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've started this in https://github.com/coniks-sys/coniks-go/tree/generic-auditor What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few first nitpicks/comments/questions while digging through the code... More comments on the general design later/tomorrow.
Also, there is a merge conflict in this pull (rebase onto master).
protocol/auditlog.go
Outdated
|
||
// FIXME: pass Response message as param | ||
// masomel: will probably want to write a more generic function | ||
// for "catching up" on a history in case an auditor misses epochs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before we merge this, the comments should follow golang's documentation convention (start with Insert
). The FIXME
can stay but shouldn't be the first thing one gets to read. The comment should probably briefly state what the difference/relation between Insert
and Update
is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, thanks for pointing this out!
protocol/auditlog.go
Outdated
// FIXME: pass Response message as param | ||
func (l *ConiksAuditLog) Update(addr string, newSTR *m.SignedTreeRoot) error { | ||
|
||
// panic if we want to update an entry for which we don't have |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"... for which we don't know the directory" (?). Also, we don't really panic
here, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we don't. I forgot to update the comment here.
protocol/auditlog_test.go
Outdated
res, err := aud.GetObservedSTR(&AuditingRequest{ | ||
DirectoryAddr: "test-server"}) | ||
obs := res.DirectoryResponse.(*ObservedSTR) | ||
if err != ReqSuccess { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpicking: directly catch the error after it occurs (move this one line up)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I don't think that would work because I use res
below for other operations. Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this has been removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this has been updated.
@@ -2,6 +2,7 @@ | |||
// on data received from a CONIKS directory. | |||
// These include data binding proof verification, | |||
// and non-equivocation checks. | |||
// TODO: move all STR-verifying functionality to a separate module |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we open an issue for that so we won't forget about it? Or is this planned to happen in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@c633 and I are already working on this in a separate branch, but we haven't opened the PR yet.
protocol/consistencychecks.go
Outdated
@@ -100,6 +101,50 @@ func (cc *ConsistencyChecks) HandleResponse(requestType int, msg *Response, | |||
return CheckPassed | |||
} | |||
|
|||
// handleDirectorySTRs is supposed to be used by CONIKS clients to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Case doesn't match with method signature (handleDirectorySTRs vs HandleDirectorySTRs).
6b368f6
to
dfd5de8
Compare
protocol/message.go
Outdated
} | ||
return nil | ||
case *ObservedSTRs: | ||
if df.STR == nil || len(df.STR) < 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified: if len(df.STR) == 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this throw a null pointer error if we don't assert df.STR != nil
?
protocol/consistencychecks.go
Outdated
// The signKey param either comes from a client's | ||
// pinned signing key in cc, or an auditor's pinned signing key | ||
// in its history. | ||
// In the case of a client-side consistency check, verifySTRConsistency() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove this line of comment since we're no longer used cc
anymore.
protocol/consistencychecks.go
Outdated
func (cc *ConsistencyChecks) verifySTRConsistency(savedSTR, str *DirSTR) error { | ||
// It uses the signing key signKey to verify the STR's signature. | ||
// The signKey param either comes from a client's | ||
// pinned signing key in cc, or an auditor's pinned signing key |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should just be pinned signing key, or an ...
(no more cc
here).
protocol/consistencychecks.go
Outdated
// HandleDirectorySTRs is supposed to be used by CONIKS clients to | ||
// handle auditor responses, and by CONIKS auditors to handle directory | ||
// responses. | ||
func HandleDirectorySTRs(requestType int, msg *Response, signKey sign.PublicKey, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it is being used nowhere and we are working on this in #170, I would like to remove it from this PR.
protocol/message.go
Outdated
@@ -90,6 +92,34 @@ type MonitoringRequest struct { | |||
EndEpoch uint64 `json:"end_epoch"` | |||
} | |||
|
|||
// An AuditingRequest is a message with a CONIKS key directory's address | |||
// as a string that a CONIKS client sends to a CONIKS auditor, or a CONIKS auditor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this supposed to be used for an auditor to request to a directory? If so, the DirectoryAddr
field seems to be redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I first wrote this, it was supposed to be used by both clients and auditors, but this doesn't really make sense. We should have separate message types for auditor-server communication and client-auditor communication. So you're right, having the DirectoryAddr
field only makes sense for client-auditor communication.
protocol/message.go
Outdated
|
||
// An AuditingInEpochRequest is a message with a key directory's address | ||
// as a string and an epoch as a uint64 that a CONIKS client sends to | ||
// a CONIKS auditor, or a CONIKS auditor sends to a CONIKS directory, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protocol/message.go
Outdated
@@ -216,6 +262,40 @@ func NewMonitoringProof(ap []*m.AuthenticationPath, | |||
}, ReqSuccess | |||
} | |||
|
|||
// NewObservedSTR creates the response message a CONIKS auditor | |||
// sends to a client, or a CONIKS directory sends to an auditor, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we use a pub-sub architecture, will this be used between an auditor and a directory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in either case, pub-sub or request-response, the implementation of the corresponding auditor-directory message would be the same, so it would make sense to use the same function to return a list of requested STRs. Similarly, the response message type for a client-auditor request and an auditor-server request for STRs should be the same type. This being said, since this PR is only for client-auditor communication, I won't add relevant auditor-directory documentation yet.
As long as `df` is not `nil` there would be no exception as `len` returns 0
if the argument is `nil`
https://golang.org/pkg/builtin/#len
Am 04.04.2017 11:05 nachm. schrieb "Marcela Melara" <
[email protected]>:
… ***@***.**** commented on this pull request.
------------------------------
In protocol/message.go
<#155 (comment)>:
> @@ -229,6 +309,16 @@ func (msg *Response) validate() error {
case *DirectoryProofs:
// TODO: also do above assertions here
return nil
+ case *ObservedSTR:
+ if df.STR == nil {
+ return ErrMalformedAuditorMessage
+ }
+ return nil
+ case *ObservedSTRs:
+ if df.STR == nil || len(df.STR) < 1 {
Won't this throw a null pointer error if we don't assert df.STR != nil?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#155 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AHGNZuK6qN3qpBuzeAFKIH11HG1wvTAAks5rsrCqgaJpZM4LOdfy>
.
|
…r response message generic
protocol/auditlog.go
Outdated
// computeInitSTRHash is a wrapper for the digest function; | ||
// returns empty string if the STR isn't an initial STR (i.e. str.Epoch != 0) | ||
func computeInitSTRHash(initSTR *DirSTR) string { | ||
if initSTR.Epoch != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should either remove this check or panic here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I refactored this function in 92cee27 (it would be used by the clients, too).
Feel free to revert if you don't like it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This refactoring LGTM.
protocol/auditlog.go
Outdated
// log; the auditor will add an entry for each CONIKS directory | ||
// the first time it observes an STR for that directory. | ||
func NewAuditLog() ConiksAuditLog { | ||
l := make(map[string]*directoryHistory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return make(map[string]*directoryHistory)
protocol/auditlog.go
Outdated
) | ||
|
||
type directoryHistory struct { | ||
name string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is name
? I see below you're putting addr
there, but where / why is this used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This used to be dirName
for directory domain name (i.e. its address), which is why we assign it addr
below. My plan right now is to use this field when auditors query the directories they log every epoch.
protocol/auditlog.go
Outdated
// validate the entries themselves. It returns true if an entry exists, | ||
// and false otherwise. | ||
func (l ConiksAuditLog) IsKnownDirectory(dirInitHash string) bool { | ||
h := l[dirInitHash] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_, ok := l[dirInitHash]
return ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still getting used to some Go idioms...
protocol/auditlog.go
Outdated
// masomel: will probably want to write a more generic function | ||
// for "catching up" on a history in case an auditor misses epochs | ||
func (l ConiksAuditLog) Insert(addr string, signKey sign.PublicKey, | ||
hist map[uint64]*DirSTR) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hist
is confusing here ... maybe snaps
instead?
protocol/auditlog.go
Outdated
hist map[uint64]*DirSTR) error { | ||
|
||
// make sure we're getting an initial STR at the very least | ||
if len(hist) < 1 && hist[0].Epoch != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hist
is a map so it's possible that the length is greater than 1 but hist[0]
returns nil
. Since you're using it in several places below, cache it as initSTR, ok := hist[0]
and then check ok
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Can we change it to a slice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A slice would also make sense. Then we would have to check that the epoch for the STR in each element corresponds to the index, which seems fine to me.
protocol/auditlog.go
Outdated
// in this particular call, the latestSTR has already been | ||
// inserted into the snapshots map in the loop above | ||
h.updateLatestSTR(hist[endEp-1]) | ||
l[dirInitHash] = h |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe don't expose the internals of l
and add a method, l.Add(dirInitHash, h)
or something.
protocol/auditlog.go
Outdated
return ErrAuditLog | ||
} | ||
|
||
h := l[dirInitHash] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same thing here, l.Get(dirInitHash)
or similar.
protocol/auditlog.go
Outdated
|
||
// verify the consistency of each new STR before inserting | ||
// into the audit log | ||
err := verifySTRConsistency(signKey, h.snapshots[ep-1], str) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the comment below, but this would then become (signKey, h.lastestSTR, str)
} | ||
|
||
// update the latest STR | ||
h.updateLatestSTR(newSTR) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the refactor suggested above, these two operations (verifySTRConsistency
, updateLatestSTR
) can be combined into an h.internalUpdate(newSTR)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of what I'm doing for #170, I need to see if it makes sense to refactor these operations both on the client and auditor. I'll probably hold off on that for now.
protocol/auditlog.go
Outdated
return NewErrorResponse(ReqUnknownDirectory), ReqUnknownDirectory | ||
} | ||
|
||
h := l[req.DirInitSTRHash] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or, maybe we should embrace that it's a map and always just use h, ok :=
and drop the IsKnownDirectory
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protocol/auditlog.go
Outdated
// dirInitHash from the ConiksAuditLog. | ||
// Get() also returns a boolean indicating whether the requested dirInitHash | ||
// is present in the log. | ||
func (l ConiksAuditLog) Get(dirInitHash string) (*directoryHistory, bool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we unexport this function? Same with Set
.
protocol/auditlog.go
Outdated
snaps []*DirSTR) error { | ||
|
||
// make sure we're getting an initial STR at the very least | ||
if len(snaps) < 1 && snaps[0].Epoch != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be len(snaps) < 1 || snaps[0].Epoch != 0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops yes, this should be an OR. Thank you for catching that.
protocol/auditlog.go
Outdated
// (i.e. snaps is missing an epoch between 0 and the latest given) | ||
for i := 1; i < len(snaps); i++ { | ||
str := snaps[i] | ||
if str == nil || str.Epoch != uint64(i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The verifySTRConsistency
would make sure that str.Epoch == i
, so we can remove the check here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is only needed because snaps
is a slice, and it's being checked in the loop. This property isn't inherent in the consistency check. Plus, verifySTRConsistency
already does this check implicitly for one STR when it calls VerifyHashchain
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do think that this property is inherent in the consistency check, since we are verify using the initial STR, and it would fail if str.Epoch != latestSTR.Epoch + 1
, which means str.Epoch == i
has to be true.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is that i == str.Epoch
is only meaningful because we expect the snaps
slice to have this property. i
isn't meaningful to consistency checks in the general sense, so I don't see why we should impose this particular assumption on the consistency checks. And VerifyHashchain
called in verifySTRConsistency
already does the str.Epoch != latestSTR.Epoch + 1
check.
protocol/auditlog.go
Outdated
|
||
// verify the consistency of each new STR before inserting | ||
// into the audit log | ||
err := verifySTRConsistency(signKey, h.latestSTR, str) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if err := verifySTRConsistency(signKey, h.latestSTR, str); err != nil {
return err
}
This reverts commit 7e54087. Conflicts: protocol/auditlog.go
Part of #151
TODO: